package com.google.code.jcooky.rpc.protocol;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONObject;

import com.google.code.jcooky.rpc.transport.Transport;
import com.google.code.jcooky.rpc.utils.JsonUtils;

/**
 * send
 * {service: "Class Name", method: "Function Name", arguments: [{key: "arg name", type:"arg type", value:"arg value"}, ... ] }
 * recv
 * {bean: "Bean Class Name", return: "return value"}
 * 
 * @author JCooky
 * 
 */
public class JSONProtocol implements Protocol {
	private Transport transport;
	
	private Map<String, Object> model = new HashMap<String, Object>();
	
	public JSONProtocol(Transport transport) {
		this.transport = transport;
		
		clear();
	}
	
	public void clear() {
		model.clear();
	}
	
	public void setClass(String className) {
		if(model.containsKey(className)) throw new RuntimeException(className + "이 이미 등록되었습니다.");
		
		model.put("service", className);
	}

	public void setClass(Class<?> klass) {
		setClass(klass.getName());
	}

	public void addArguments(String key, Class<?> type, Object value) {
		if(!model.containsKey("arguments")) {
			model.put("arguments", new ArrayList<Map<String, Object>>());
		}
		List<Map<String, Object>> args = (List<Map<String, Object>>)model.get("arguments");
		Map<String, Object> arg = new HashMap<String, Object>();
		arg.put("key", key);
		arg.put("type", type);
		arg.put("value", value);
		args.add(arg);
	}

	public void setFunction(String functionName) {
		if(model.containsKey("method")) throw new RuntimeException(functionName + "이 이미 등록되었습니다.");
		model.put("method", functionName);
	}

	public void call() {
		JSONObject jsonObj = JSONObject.fromObject(model);
		transport.send(jsonObj.toString());
	}

	public Object getReturn() throws ClassNotFoundException {
		JSONObject jsonObj = JSONObject.fromObject(transport.recv());
		Class<?> beanClass = ClassLoader.getSystemClassLoader().loadClass(jsonObj.getString("bean"));
		return JsonUtils.getObjectFromJSON(beanClass, jsonObj.get("return"));
	}
}
